#region Copyright (c) 2006-2009 Widgetsphere LLC, All Rights Reserved
//--------------------------------------------------------------------- *
//                          Widgetsphere  LLC                           *
//             Copyright (c) 2006-2009 All Rights reserved              *
//                                                                      *
//                                                                      *
//This file and its contents are protected by United States and         *
//International copyright laws.  Unauthorized reproduction and/or       *
//distribution of all or any portion of the code contained herein       *
//is strictly prohibited and will result in severe civil and criminal   *
//penalties.  Any violations of this copyright will be prosecuted       *
//to the fullest extent possible under law.                             *
//                                                                      *
//THE SOURCE CODE CONTAINED HEREIN AND IN RELATED FILES IS PROVIDED     *
//TO THE REGISTERED DEVELOPER FOR THE PURPOSES OF EDUCATION AND         *
//TROUBLESHOOTING. UNDER NO CIRCUMSTANCES MAY ANY PORTION OF THE SOURCE *
//CODE BE DISTRIBUTED, DISCLOSED OR OTHERWISE MADE AVAILABLE TO ANY     *
//THIRD PARTY WITHOUT THE EXPRESS WRITTEN CONSENT OF WIDGETSPHERE LLC   *
//                                                                      *
//UNDER NO CIRCUMSTANCES MAY THE SOURCE CODE BE USED IN WHOLE OR IN     *
//PART, AS THE BASIS FOR CREATING A PRODUCT THAT PROVIDES THE SAME, OR  *
//SUBSTANTIALLY THE SAME, FUNCTIONALITY AS ANY WIDGETSPHERE PRODUCT.    *
//                                                                      *
//THE REGISTERED DEVELOPER ACKNOWLEDGES THAT THIS SOURCE CODE           *
//CONTAINS VALUABLE AND PROPRIETARY TRADE SECRETS OF WIDGETSPHERE,      *
//INC.  THE REGISTERED DEVELOPER AGREES TO EXPEND EVERY EFFORT TO       *
//INSURE ITS CONFIDENTIALITY.                                           *
//                                                                      *
//THE END USER LICENSE AGREEMENT (EULA) ACCOMPANYING THE PRODUCT        *
//PERMITS THE REGISTERED DEVELOPER TO REDISTRIBUTE THE PRODUCT IN       *
//EXECUTABLE FORM ONLY IN SUPPORT OF APPLICATIONS WRITTEN USING         *
//THE PRODUCT.  IT DOES NOT PROVIDE ANY RIGHTS REGARDING THE            *
//SOURCE CODE CONTAINED HEREIN.                                         *
//                                                                      *
//THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE.              *
//--------------------------------------------------------------------- *
#endregion
using System;
using System.Drawing;
using System.Collections;
using Widgetsphere.Generator.Common.GeneratorFramework;
using System.Windows.Forms;
using Widgetsphere.Generator.Common.Util;
using System.Xml;
using Widgetsphere.Generator.Forms;
using System.Collections.Generic;

namespace Widgetsphere.Generator.Models
{
	public class TableCollectionController : BaseModelObjectController
	{
		#region Member Variables

		private ContextMenu PopupMenu = null;
		private ListView ControllerListView = null;

		#endregion

		#region Constructor

		protected internal TableCollectionController(IModelObject modelObject)
			: base(modelObject)
		{
			System.Diagnostics.Debug.WriteLine("TableCollectionController:Constructor");
		}

		#endregion

		#region BaseModelObjectController Members

		public override ModelObjectTreeNode Node
		{
			get
			{
				if (_node == null)
				{
					_node = new TableCollectionNode(this);
				}
				return _node;
			}
		}

		public override ModelObjectUserInterface UIControl
		{
			get
			{
				if (this.UserInterface == null)
				{
					PanelUIControl ctrl = new PanelUIControl();
					ControllerListView = new ListView();
					ControllerListView.View = View.Details;
					ControllerListView.HideSelection = false;
					ControllerListView.FullRowSelect = true;
					ControllerListView.Dock = DockStyle.Fill;
					ControllerListView.Columns.Add("Name", 250, HorizontalAlignment.Left);
					ControllerListView.Columns.Add("Code Facade", 250, HorizontalAlignment.Left);
					ControllerListView.Columns.Add("Columns", 250, HorizontalAlignment.Left);
					System.Type[] typeList = new System.Type[] { typeof(string), typeof(string), typeof(int) };
					Widgetsphere.Generator.Common.Forms.ListViewComparer comparer = new Widgetsphere.Generator.Common.Forms.ListViewComparer(ControllerListView, typeList);
					ControllerListView.ListViewItemSorter = comparer;
					comparer.Column = 0;
					ControllerListView.Sorting = SortOrder.Ascending;
					ControllerListView.SmallImageList = Widgetsphere.Generator.ImageHelper.GetImageList();
					ctrl.MainPanel.Controls.Add(ControllerListView);
					ctrl.Dock = DockStyle.Fill;

					ControllerListView.MouseUp += new MouseEventHandler(listView_MouseUp);
					ControllerListView.KeyUp += new KeyEventHandler(listView_KeyUp);
					ControllerListView.DoubleClick += new EventHandler(listView_DoubleClick);

					PopupMenu = new ContextMenu();
					ControllerListView.ContextMenu = PopupMenu;
					MenuItem menuDelete = new MenuItem("Delete");
					menuDelete.Click += new EventHandler(menuDelete_Click);
					PopupMenu.MenuItems.Add(menuDelete);

					this.UserInterface = ctrl;
				}

				//Load the list
				ControllerListView.Items.Clear();
				foreach (Table table in (TableCollection)this.Object)
				{
					ListViewItem newItem = new ListViewItem(table.Name);
					if (table.AssociativeTable)
						newItem.ImageIndex = ImageHelper.GetImageIndex(ImageConstants.TableAssociative);
					else
						newItem.ImageIndex = ImageHelper.GetImageIndex(ImageConstants.Table);
					newItem.Tag = table;
					newItem.Name = table.Key;
					newItem.SubItems.Add(table.CodeFacade);
					newItem.SubItems.Add(table.Columns.Count.ToString());
					ControllerListView.Items.Add(newItem);
				}

				ControllerListView.Sort();

				return this.UserInterface;
			}
		}

		private void listView_DoubleClick(object sender, System.EventArgs e)
		{
			if (this.ControllerListView.SelectedItems.Count == 1)
			{
				ListViewItem item = this.ControllerListView.SelectedItems[0];
				TreeNode[] nodeList = this.Node.Nodes.Find(((Table)item.Tag).Key, false);
				if (nodeList.Length > 0)
				{
					if (this.Node.TreeView != null)
						this.Node.TreeView.SelectedNode = nodeList[0];
				}
			}
		}

		void listView_KeyUp(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == Keys.Delete)
			{
				menuDelete_Click(null, null);
			}
		}

		void listView_MouseUp(object sender, MouseEventArgs e)
		{
			if (e.Button == MouseButtons.Right)
			{
				PopupMenu.Show((ListView)sender, new Point(e.X, e.Y));
			}
		}

		private void menuDelete_Click(object sender, System.EventArgs e)
		{
			if (MessageBox.Show("Do you wish to delete the selected items?", "Delete?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
				return;

			foreach (ListViewItem item in ControllerListView.SelectedItems)
				((TableCollection)this.Object).Remove(((Table)item.Tag).Id);

			//Remove the item from the listview
			for (int ii = ControllerListView.SelectedItems.Count - 1; ii >= 0; ii--)
			{
				//Remove the item from the tree
				this.Node.Nodes.Remove(this.Node.Nodes[ControllerListView.SelectedItems[ii].Name]);
				//Remove Listitem
				ControllerListView.Items.Remove(ControllerListView.SelectedItems[ii]);
			}

			this.Object.Root.Dirty = true;

		}

		public override MenuCommand[] GetMenuCommands()
		{
			MenuCommand mcAddTable = new DefaultMenuCommand();
			mcAddTable.Text = "New Table";
			mcAddTable.Click += new EventHandler(AddTableMenuClick);

			MenuCommand menuSep5 = new DefaultMenuCommand();
			menuSep5.Text = "-";

			MenuCommand menuUpdateTableName = new DefaultMenuCommand();
			menuUpdateTableName.Text = "Update Table Names...";
			menuUpdateTableName.Click += new EventHandler(UpdateTableNameMenuClick);

			MenuCommand menuUpdateCodeFace = new DefaultMenuCommand();
			menuUpdateCodeFace.Text = "Update Table Codefacades...";
			menuUpdateCodeFace.Click += new EventHandler(UpdateCodefacadeMenuClick);

			MenuCommand menuSep4 = new DefaultMenuCommand();
			menuSep4.Text = "-";

			MenuCommand menuUpdateColumnName = new DefaultMenuCommand();
			menuUpdateColumnName.Text = "Update Column Names...";
			menuUpdateColumnName.Click += new EventHandler(UpdateColumnNameColumnMenuClick);

			MenuCommand menuUpdateColumnCodeFace = new DefaultMenuCommand();
			menuUpdateColumnCodeFace.Text = "Update Column Codefacades...";
			menuUpdateColumnCodeFace.Click += new EventHandler(UpdateCodefacadeColumnMenuClick);

			MenuCommand menuSep = new DefaultMenuCommand();
			menuSep.Text = "-";

			MenuCommand mcAddUnitTest = new DefaultMenuCommand();
			mcAddUnitTest.Text = "Add Unit Tests";
			mcAddUnitTest.Click += new EventHandler(AddUnitTestMenuClick);

			MenuCommand mcClearUnitTest = new DefaultMenuCommand();
			mcClearUnitTest.Text = "Clear Unit Tests";
			mcClearUnitTest.Click += new EventHandler(ClearUnitTestMenuClick);

			MenuCommand menuSep2 = new DefaultMenuCommand();
			menuSep2.Text = "-";

			MenuCommand mcAuditRoot = new DefaultMenuCommand();
			mcAuditRoot.Text = "Audits";

			MenuCommand mcAddCreateAudit = new DefaultMenuCommand();
			mcAddCreateAudit.Text = "Add Create Audits";
			mcAddCreateAudit.Click += new EventHandler(AddCreateAuditMenuClick);
			mcAuditRoot.MenuItems.Add(mcAddCreateAudit);

			MenuCommand mcRemoveCreateAudit = new DefaultMenuCommand();
			mcRemoveCreateAudit.Text = "Remove Create Audits";
			mcRemoveCreateAudit.Click += new EventHandler(RemoveCreateAuditMenuClick);
			mcAuditRoot.MenuItems.Add(mcRemoveCreateAudit);

			MenuCommand menuSep10 = new DefaultMenuCommand();
			menuSep10.Text = "-";
			mcAuditRoot.MenuItems.Add(menuSep10);

			MenuCommand mcAddModifyAudit = new DefaultMenuCommand();
			mcAddModifyAudit.Text = "Add Modify Audits";
			mcAddModifyAudit.Click += new EventHandler(AddModifyAuditMenuClick);
			mcAuditRoot.MenuItems.Add(mcAddModifyAudit);

			MenuCommand mcRemoveModifyAudit = new DefaultMenuCommand();
			mcRemoveModifyAudit.Text = "Remove Modify Audits";
			mcRemoveModifyAudit.Click += new EventHandler(RemoveModifyAuditMenuClick);
			mcAuditRoot.MenuItems.Add(mcRemoveModifyAudit);

			MenuCommand menuSep11 = new DefaultMenuCommand();
			menuSep11.Text = "-";
			mcAuditRoot.MenuItems.Add(menuSep11);

			MenuCommand mcAddTimestampAudit = new DefaultMenuCommand();
			mcAddTimestampAudit.Text = "Add Timestamp Audits";
			mcAddTimestampAudit.Click += new EventHandler(AddTimestampAuditMenuClick);
			mcAuditRoot.MenuItems.Add(mcAddTimestampAudit);

			MenuCommand mcRemoveTimestampAudit = new DefaultMenuCommand();
			mcRemoveTimestampAudit.Text = "Remove Timestamp Audits";
			mcRemoveTimestampAudit.Click += new EventHandler(RemoveTimestampAuditMenuClick);
			mcAuditRoot.MenuItems.Add(mcRemoveTimestampAudit);

			MenuCommand menuSep3 = new DefaultMenuCommand();
			menuSep3.Text = "-";

			MenuCommand menuPaste = new DefaultMenuCommand();
			menuPaste.Text = "Paste";
			menuPaste.Click += new EventHandler(PasteMenuClick);

			return new MenuCommand[] { 
				mcAddTable, menuSep5,
				menuUpdateTableName, menuUpdateCodeFace, menuSep4, 
				menuUpdateColumnName, menuUpdateColumnCodeFace, menuSep, 
				mcAddUnitTest, mcClearUnitTest, 
				menuSep2, 
				mcAuditRoot,
				menuSep3, menuPaste };
		}

		public override MessageCollection Verify()
		{
			try
			{
				MessageCollection retval = new MessageCollection();
				retval.AddRange(base.Verify());

				TableCollection tableCollection = (TableCollection)this.Object;

				#region Check for zero tables
				if (tableCollection.Count == 0)
				{
					retval.Add(MessageTypeConstants.Error, ValidationHelper.ErrorTextNoTables, null);
				}
				#endregion

				#region Check for duplicate names
				Hashtable nameList = new Hashtable();
				foreach (Table table in tableCollection)
				{
					if (table.Generated)
					{
						string name = table.Name.ToLower();
						if (nameList.ContainsKey(name))
							retval.Add(MessageTypeConstants.Error, string.Format(ValidationHelper.ErrorTextDuplicateName, table.Name), this);
						else
							nameList.Add(name, "");
					}
				}
				#endregion

				#region Check for duplication relationship names

				Dictionary<string, List<Table>> duplicateList = new Dictionary<string, List<Table>>();
				foreach (Table table in tableCollection)
				{
					foreach (Reference reference in table.Relationships)
					{
						Relation relation = (Relation)reference.Object;
						Table childTable = (Table)relation.ChildTableRef.Object;
						if (childTable != null)
						{
							string key = "";
							if (string.Compare(table.Name, childTable.Name, true) < 0)
								key = table.Name + relation.RoleName + childTable.Name;
							else
								key = childTable.Name + relation.RoleName + table.Name;

							if (duplicateList.ContainsKey(key))
							{
								duplicateList[key].Add(table);
							}
							else
							{
								List<Table> newList = new List<Table>();
								newList.Add(table);
								duplicateList.Add(key, newList);
							}
						}
						
					}

					foreach (string key in duplicateList.Keys)
					{
						if (duplicateList[key].Count > 1)
						{
							string theTables = "";
							foreach (Table t in duplicateList[key])
							{
								theTables += t.Name + ", ";
							}
							if (theTables.EndsWith(", ")) theTables = theTables.Substring(0, theTables.Length - 2);
							retval.Add(MessageTypeConstants.Error, string.Format(ValidationHelper.ErrorTextConflictingRelationships, theTables), this);
						}
					}

				}

				#endregion

				if (retval.Count == 0)
				{
					//Check for duplicate codefacades
					nameList = new Hashtable();
					foreach (Table table in tableCollection)
					{
						if (table.Generated)
						{
							string name = table.PascalName.ToLower();
							if (nameList.ContainsKey(name))
								retval.Add(MessageTypeConstants.Error, string.Format(ValidationHelper.ErrorTextDuplicateCodeFacade, table.Name), this);
							else
								nameList.Add(name, "");
						}
					}
				}

				return retval;

			}
			catch (Exception ex)
			{
				throw;
			}

		}

		public override bool DeleteObject()
		{
			return false;
		}

		public override void Refresh()
		{
			this.UserInterface = null;
		}

		#endregion

		#region Menu Handlers

		private void UpdateCodefacadeColumnMenuClick(object sender, System.EventArgs e)
		{
			ColumnCodeFacadeUpdateForm F = new ColumnCodeFacadeUpdateForm(null, (ModelRoot)((TableCollection)this.Object).Root, ColumnCodeFacadeUpdateForm.FieldSettingConstants.CodeFacade);
			F.ShowDialog();
		}

		private void UpdateColumnNameColumnMenuClick(object sender, System.EventArgs e)
		{
			ColumnCodeFacadeUpdateForm F = new ColumnCodeFacadeUpdateForm(null, (ModelRoot)((TableCollection)this.Object).Root, ColumnCodeFacadeUpdateForm.FieldSettingConstants.Name);
			F.ShowDialog();
		}

		private void UpdateCodefacadeMenuClick(object sender, System.EventArgs e)
		{
			TableCodeFacadeUpdateForm F = new TableCodeFacadeUpdateForm((TableCollection)this.Object, TableCodeFacadeUpdateForm.FieldSettingConstants.CodeFacade);
			F.ShowDialog();
		}

		private void UpdateTableNameMenuClick(object sender, System.EventArgs e)
		{
			TableCodeFacadeUpdateForm F = new TableCodeFacadeUpdateForm((TableCollection)this.Object, TableCodeFacadeUpdateForm.FieldSettingConstants.Name);
			F.ShowDialog();
		}

		private void AddTableMenuClick(object sender, System.EventArgs e)
		{
			Table table = ((TableCollection)this.Object).Add();
			this.OnItemChanged(this, new System.EventArgs());
		}

		private void AddUnitTestMenuClick(object sender, System.EventArgs e)
		{
			if (MessageBox.Show("This action will add unit tests to all tables. Do you wish to proceeed?", "Add Unit Tests?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
			{
				TableCollection tableCollection = (TableCollection)this.Object;
				foreach (Table table in tableCollection)
				{
					if (table.AllowModification)
					{
						table.AddUnitTests();
					}
				}
				this.OnItemChanged(this, new System.EventArgs());
			}
		}

		private void ClearUnitTestMenuClick(object sender, System.EventArgs e)
		{
			if (MessageBox.Show("This action will remove all unit tests from all tables. Do you wish to proceeed?", "Add Unit Tests?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
			{
				TableCollection tableCollection = (TableCollection)this.Object;
				foreach (Table table in tableCollection)
				{
					table.UnitTestDependencies.Clear();
					table.AllowUnitTest = Table.UnitTestSettingsConstants.StubOnly;
				}
				this.OnItemChanged(this, new System.EventArgs());
			}
		}

		private void AddCreateAuditMenuClick(object sender, System.EventArgs e)
		{
			TableCollection tableCollection = (TableCollection)this.Object;
			foreach (Table table in tableCollection)
			{
				table.AllowCreateAudit = true;
			}
		}

		private void RemoveCreateAuditMenuClick(object sender, System.EventArgs e)
		{
			TableCollection tableCollection = (TableCollection)this.Object;
			foreach (Table table in tableCollection)
			{
				table.AllowCreateAudit = false;
			}
			this.OnItemChanged(this, new System.EventArgs());
		}

		private void AddModifyAuditMenuClick(object sender, System.EventArgs e)
		{
			TableCollection tableCollection = (TableCollection)this.Object;
			foreach (Table table in tableCollection)
			{
				table.AllowModifiedAudit = true;
			}
			this.OnItemChanged(this, new System.EventArgs());
		}

		private void RemoveModifyAuditMenuClick(object sender, System.EventArgs e)
		{
			TableCollection tableCollection = (TableCollection)this.Object;
			foreach (Table table in tableCollection)
			{
				table.AllowModifiedAudit = false;
			}
			this.OnItemChanged(this, new System.EventArgs());
		}

		private void AddTimestampAuditMenuClick(object sender, System.EventArgs e)
		{
			TableCollection tableCollection = (TableCollection)this.Object;
			foreach (Table table in tableCollection)
			{
				table.AllowTimestamp = true;
			}
			this.OnItemChanged(this, new System.EventArgs());
		}

		private void RemoveTimestampAuditMenuClick(object sender, System.EventArgs e)
		{
			TableCollection tableCollection = (TableCollection)this.Object;
			foreach (Table table in tableCollection)
			{
				table.AllowTimestamp = false;
			}
			this.OnItemChanged(this, new System.EventArgs());
		}

		private void PasteMenuClick(object sender, System.EventArgs e)
		{
			if (Clipboard.ContainsData("ws.model.table"))
			{
				XmlDocument document = new XmlDocument();
				document.LoadXml((string)Clipboard.GetData("ws.model.table"));

				Table table = ((TableCollection)this.Object).Add();
				int id = table.Id;
				table.XmlLoad(document.DocumentElement.SelectSingleNode("table"));
				table.SetId(id);
				table.SetKey(Guid.NewGuid().ToString());
				table.Name = "[" + table.Name + "]";
				table.Columns.Clear();
				table.Relationships.Clear();
				table.CustomRetrieveRules.Clear();

				foreach (XmlNode node in document.DocumentElement.SelectSingleNode("columnList").ChildNodes)
				{
					Column column = ((ModelRoot)this.Object.Root).Database.Columns.Add();
					id = column.Id;
					column.XmlLoad(node);
					column.SetId(id);
					column.SetKey(Guid.NewGuid().ToString());
					table.Columns.Add(column.CreateRef());
					column.ParentTableRef = table.CreateRef();
				}
				this.OnItemChanged(this, new System.EventArgs());
			}
		}

		#endregion

	}
}